﻿import asyncio
import json
import os
from http.server import BaseHTTPRequestHandler, HTTPServer
from playwright.async_api import async_playwright, TimeoutError as PlaywrightTimeoutError
from typing import Optional

# --- 配置区 (请务必检查这里的配置) ---
# ‼️ 关键配置: Chromium 浏览器路径
CHROMIUM_EXECUTABLE_PATH = r"E:\\google\\Chrome\\Application\\chrome.exe"

# ‼️ 关键配置: 您要监控的目标用户的UID
#    这个方案的成败完全取决于这位用户是否发布了“粉丝可见”的微博。
#    我们从您最早的截图中获取了这个UID，您可以根据需要修改。
TARGET_UID = "5069029750" 

# 其他配置
AUTH_STATE_FILE = "weibo_auth_state.json" 

# 服务器配置
HOST = "localhost"
PORT = 8080

# --- 主逻辑区 ---
async def refresh_and_get_cookie() -> Optional[str]:
    """
    使用“间接验证方案”。
    通过访问目标用户的主页，并检查其最近的微博中是否存在“粉丝可见”类型的帖子，
    来判断当前Cookie是否依然有效。
    """
    if not os.path.exists(AUTH_STATE_FILE):
        print(f"❌ 错误：找不到认证文件 '{AUTH_STATE_FILE}'，无法刷新Cookie。")
        return None

    print("\n🔄 开始刷新Cookie (使用间接验证方案)...")
    async with async_playwright() as p:
        try:
            browser = await p.chromium.launch(
                headless=True,
                executable_path=CHROMIUM_EXECUTABLE_PATH,
                args=["--no-sandbox", "--disable-gpu"]
            )
        except Exception as e:
            print(f"❌ 浏览器启动失败: {e}")
            return None

        context = await browser.new_context(storage_state=AUTH_STATE_FILE)
        page = await context.new_page()
        
        # ✨ 验证逻辑改变：构建目标用户主页的API URL ✨
        validation_url = f"https://m.weibo.cn/api/container/getIndex?type=uid&value={TARGET_UID}&containerid=107603{TARGET_UID}"
        print("urlurlurlurl")
        print(validation_url)
        print("urlurlurlurl")
        
        try:
            print(f"🔍 正在访问目标用户API: uid={TARGET_UID}")
            
            await page.goto(validation_url, wait_until="networkidle", timeout=45000)

            print("✅ API响应获取成功，正在解析内容...")
            
            json_text = await page.evaluate('document.body.textContent')

            if not json_text or not json_text.strip():
                print("❌ API返回了空内容。Cookie可能已完全失效或被屏蔽。")
                await browser.close()
                return None
            
            cookie_is_valid = False # 初始化验证状态为无效
            
            try:
                data = json.loads(json_text)
                # ✨ 核心验证逻辑改变：遍历微博卡片 ✨
                cards = data.get('data', {}).get('cards', [])
                if not cards:
                    print(f"🤷 警告：从用户 {TARGET_UID} 主页没有获取到任何微博内容。无法进行验证。")
                
                print(f"🔍 正在检查最近的 {len(cards)} 条微博内容...")
                for card in cards:
                    # 检查是否是微博帖子 (card_type=9) 并且包含 mblog 结构
                    if card.get('card_type') == 9 and 'mblog' in card:
                        # 关键判断：检查 visible.type 是否为 10 (粉丝可见)
                        visible_type = card['mblog'].get('visible', {}).get('type')
                        if visible_type == 10:
                            print("🎉 验证成功！找到了粉丝可见的微博。Cookie有效！")
                            cookie_is_valid = True
                            break # 找到一个就足够了，跳出循环
                
                if not cookie_is_valid:
                    print("❌ 验证失败：在目标用户的最新微博中，未能找到任何“粉丝可见”的帖子。")
                    print("   这可能意味着两件事：")
                    print("   1. 您的Cookie已过期 (可能性大)。")
                    print(f"   2. 您的Cookie有效，但用户 {TARGET_UID} 最近没有发粉丝可见的微博 (可能性小)。")
                    await browser.close()
                    return None

            except (json.JSONDecodeError, KeyError) as e:
                print(f"❌ 解析API响应失败！这通常意味着Cookie已失效，微博返回了登录页面。")
                print(f"   错误详情: {e}")
                await browser.close()
                return None

        except PlaywrightTimeoutError:
            print(f"❌ 访问API超时。网络问题或微博服务器无响应。")
            await browser.close()
            return None
        except Exception as e:
            print(f"❌ 验证登录时发生未知错误: {e}")
            await browser.close()
            return None
        
        print("🍪 正在提取最新的Cookie...")
        cookies = await context.cookies()
        if not cookies:
            print("❌ 未能从浏览器上下文中提取到任何Cookie。")
            await browser.close()
            return None

        cookie_string = "; ".join([f"{c['name']}={c['value']}" for c in cookies])
        
        print("✅ Cookie提取成功！")
        await browser.close()
        return cookie_string

class CookieRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        print(f"\n[诊断信息] 收到来自 {self.client_address[0]} 的请求，请求路径为: '{self.path}'")
        if self.path == '/' or self.path == '/get-cookie':
            print("\n- - - - - - - - - - - - - - - - - - - -")
            print(f"路径正确！开始为 {self.client_address[0]} 刷新Cookie...")
            cookie = asyncio.run(refresh_and_get_cookie())
            if cookie:
                self.send_response(200)
                self.send_header('Content-type', 'text/plain; charset=utf-8')
                self.end_headers()
                self.wfile.write(cookie.encode('utf-8'))
                print("✅ 成功将新Cookie发送给程序。")
            else:
                self.send_response(500)
                self.end_headers()
                self.wfile.write(b"Failed to refresh cookie.")
                print("❌ 刷新Cookie失败，已向程序返回错误。")
            print("- - - - - - - - - - - - - - - - - - - -")
        else:
            self.send_response(404)
            self.send_header('Content-type', 'text/plain; charset=utf-8')
            self.end_headers()
            self.wfile.write(b"Error: Endpoint not found.")
            print(f"❌ 路径错误！已向 {self.client_address[0]} 返回 404 Not Found。")

def run_server():
    if not os.path.exists(AUTH_STATE_FILE):
        print(f"❌ 严重错误：找不到认证文件 '{AUTH_STATE_FILE}'。")
        print("请先成功运行 get_cookie.py 来生成此文件。")
        return
    server_address = (HOST, PORT)
    httpd = HTTPServer(server_address, CookieRequestHandler)
    print(f"\n📡 Python服务器已启动，正在监听 http://{HOST}:{PORT} ...")
    print("这个窗口需要一直保持运行，以便随时为程序提供有效的Cookie。")
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        print("\n🛑 服务器已停止。")
        httpd.server_close()

if __name__ == '__main__':
    run_server()
